package com.tom.demo.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义线程池工厂类
 */
@Slf4j
public class ThreadPoolFactoryManage {
    /**
     * 主要解释
     * ExecutorService 是 Java 中用于管理和执行异步任务的高级接口，可以理解为一个线程池执行器实例，
     * 属于 java.util.concurrent包下。
     * -它负责提交任务（Runnable/Callable）、
     * -调度执行、
     * -管理线程池、
     * -以及提供任务结果的 Future 等能力
     */
    private static final ExecutorService CUSTOMIZE_EXECUTOR;
    /**
     * cpu核心数量,我们可以直接获取当前服务器cpu核心数
     */
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    /**
     * 核心线程数，默认为 CPU 核心数。
     * 核心线程会一直存活（除非 allowCoreThreadTimeOut=true）。
     */
    private static final int CORE_POOL_SIZE = CPU_COUNT;
    /**
     * 最大线程数，默认为 CPU 核心数 * 2。
     * 当队列满且线程数未达上限时，会创建新线程。
     */
    private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE * 2;
    /**
     * 线程空闲超时时间。
     * 当线程数 > corePoolSize 时，空闲线程超过此时间将被回收。
     * 由于 allowCoreThreadTimeOut(true)，核心线程也会超时回收。
     */
    private static final long KEEP_ALIVE_TIME = 30L;
    /**
     * 任务队列容量（有界队列）。
     * 使用有界队列可防止内存溢出，但需配合合理的拒绝策略。
     */
    private static final int QUEUE_CAPACITY = 200;

    /**
     * 超时时间单位时间单位(SECONDS=秒)
     */
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;

    /*
     * 静态初始化线程池执行器实例
     */
    static {
        CUSTOMIZE_EXECUTOR = createSharedExecutor();
    }

    /**
     * 创建线程池执行器实例
     * @return
     */
    private static ExecutorService createSharedExecutor() {
        //构建一个有界队列防止OOM  LinkedBlockingQueue 高并发下吞吐更高，但内存占用略高ArrayBlockingQueue更高
        BlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>(QUEUE_CAPACITY);
        //构建一个线程工厂
        ThreadFactory threadFactory = new ThreadFactory() {
            private final AtomicInteger threadNumber = new AtomicInteger(1);
            private final ThreadGroup threadGroup = new ThreadGroup("CustomizeThreadPoolFactory");

            @Override
            public Thread newThread(@NotNull Runnable runnable) {
                //创建线程，并且设置线程分组和，线程的名称编号
                Thread thread = new Thread(threadGroup,runnable, "wafer-check-thread-" + threadNumber.getAndIncrement(),0);
                // 关键：不要设为守护线程！否则 JVM 退出时任务会丢失
                thread.setDaemon(false);
                // 设置线程优先级，如果主线程（main thread）的优先级是 5，那么新创建的线程默认也是 5。默认继承父线程的优先级
                thread.setPriority(Thread.NORM_PRIORITY);
                //为当前线程设置一个未捕获异常的处理器（Uncaught Exception Handler），用于捕获并处理该线程中未被 try-catch 捕获的异常。
                thread.setUncaughtExceptionHandler((t, ex) -> log.error("Uncaught exception in thread: {}, message: {}", t.getName(), ex.getMessage(), ex));
                return thread;
            }
        };
        /*
         * 获取一个决绝策略对象
         *      当以下情况发生时，线程池会拒绝新任务：
         * -线程池已关闭（shutdown() 或 shutdownNow() 被调用）；
         * -任务队列已满（比如使用了有界队列）；
         * -线程数量已达 maximumPoolSize。
         * -此时，ThreadPoolExecutor 会调用 RejectedExecutionHandler.rejectedExecution(Runnable r, ThreadPoolExecutor executor) 方法来处理被拒绝的任务。
         *
         *AbortPolicy（默认策略）
         * 行为：直接抛出 RejectedExecutionException 异常
         * 适用场景：希望立即知道任务被拒绝，便于监控或告警
         *
         * CallerRunsPolicy:调用者运行策略
         * 行为：由提交任务的线程（即调用 execute() 的线程）自己执行该任务。
         * 效果：
         *    -不会丢弃任务；
         *    -会阻塞提交线程，从而减缓新任务的提交速度（一种“背压”机制）；
         *    -适用于任务提交速率可控、且希望保证任务不丢失的场景。
         *
         * DiscardPolicy（丢弃策略）
         * 行为：静默丢弃被拒绝的任务，不抛异常。
         * 风险：任务可能悄无声息地丢失，难以排查问题。
         * 适用场景：允许任务丢失，且不希望影响系统稳定性
         *
         * DiscardOldestPolicy（丢弃最旧任务策略）
         * 行为：丢弃任务队列中最老的（即等待最久的）任务,然后尝试重新提交当前任务（注意：不是直接执行，而是再次尝试入队）
         * 注意：如果线程池已关闭，仍然会丢弃当前任务
         * 适用场景：希望优先处理新任务，比如实时性要求高的系统。
         *
         * 自定义拒绝策略
         * 你也可以实现 RejectedExecutionHandler 接口，定义自己的处理逻辑
         * 记录日志
         * 发送告警
         * 将任务存入数据库稍后重试
         * 降级处理等
         */
        RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.CallerRunsPolicy();

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE,
                MAXIMUM_POOL_SIZE,
                KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT,
                linkedBlockingQueue,
                threadFactory,
                rejectedExecutionHandler
        );
        //允许核心线程在空闲时超时回收，节省资源
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        return threadPoolExecutor;
    }

    /**
     * 提供向外暴漏获取线程池执行器的方法
     * @return
     */
    public static ExecutorService getWaferCheckExecutor() {
        return CUSTOMIZE_EXECUTOR;
    }
}
